by Ibrahim Malluf
In this chapter
Visual Basic Script, in keeping with its lightweight implementation, has limited its data types to only oneùthe variant. For those unfamiliar with Visual Basic in general, the variant is a data type that can contain a representation of almost any other data type. Strings, longs, doubles, dates, and so on are easily contained within a variant. This is what is known as weak data typing and is the opposite of the preferred strong typing of a more robust programming environment like Visual Basic Professional, where you have specific data types to contain your data. Having a weakly-typed language offers the simplicity of the variant in use for the programmer in declaring variable storage and simplicity in Visual Basic Script's implementation since the code library for VBS need only contain the functionality of the variant type. On the other hand, this simplicity also caries the danger of passing the wrong data type to a procedure that can be very hard to debug. VBScript programs can become real monsters to maintain if the programmer doesn't take care to insure some sort of procedural level data typing. It's a tradeoff that seems to work quite well.
Let's take a more in-depth look at the variant's capabilities. As I mentioned, the variant can contain any of the other data types normally associated with Visual Basic. It also automatically converts between data types where possible. When assigning a value to a variant, Visual Basic fits that value into a type that it assumes is the optimal type. Whole numbers become integer types, numbers with fractional portions become floating point types, and character values become string types without any intervention on your part. For example, if you have two variables, one containing a string and the other a numeric value, you can concatenate them without any explicit type conversions.
The result here is that MyDisplay contains the string "The Number is: 1234.5678." In most cases, you do not have to be concerned with the conversions of one data type to another since all conversions are automatic. But you need to be careful in your use of the + operator. While it concatenates strings, if you use it to concatenate two numericals or two numeric strings, they are added instead of concatenated. Therefore, always use the & operator to concatenate string type variants and the + operator to add numeric values. The following listing shows the proper method to use when concatenating a string.
MyString = "The Number is: "
MyAnswer = 1234.5678
MyDisplay = MyString & MyAnswer
The Boolean sub-type is a 16-bit signed integer, but when accessed can only return a True (û1) or False (0). In Visual Basic Script you can use either the keywords or the numeric representation of True and False. If you coerce a numeric value into a boolean variant the result is a û1 for any value other than 0. Be aware that VBScript and the browser that's containing it may not always handle booleans the same. In the example code shown in the following listing, the Alert statement of the Explorer browser displays the Boolean as a numeric value while Visual Basic Script's MsgBox procedure displays it as a keyword.
MyBool = True
Alert MyByte 'displays (-1)
MsgBox MyByte 'displays 'True'
The Byte sub-type is an 8-bit unsigned integer. It was first included with Visual Basic 4. Its main purpose was to replace the use of strings for containing binary data. Prior to Visual Basic 4, string data was a single byte unsigned integer that represented an ASCII character. This changed to the two byte Unicode system with Visual Basic 4 and made strings unreliable for carrying binary data. The advantage of the Byte sub-type in Visual Basic Script is limited to using it as an unsigned integer value up to 65535, or as a set of eight Boolean flags.
The Currency sub-type is optimized for the highly accurate manipulation of currency values or any math that requires accuracy up to 15 whole number places and four decimal places. Internally, it is an 8-byte integer with a 4-digit fixed decimal place. The numeric range of the currency type is û922,337,203,685,477.5808 to 922,337,203,685,477.5807.
The Date sub-type is a 64-bit floating point number that can represent a date from 1/1/100 to 12/31/9999. The way it works is that each whole number represents a day and the decimal numbers represent time. Negative whole numbers count back from 12/30 1899 and positive whole numbers count forward from that date. Time is represented by the digits to the right of the decimal point with .0 equal to midnight and .5 equal to 12 o'clock noon. Date sub-types recognize input either as strings that represent dates or their numeric equivalents. Listing 16.1 shows a set of date representations and how they are displayed under different circumstances.
Listing 16.1 The Different Ways a Date Value Can Be Handled
The Double sub-type is an IEEE 64-bit double precision floating point number that can represent a range from û1.79769313486232E308 to û4.94065645841247E-324 in negative numbers, and 1.79769313486232E308 to 4.94065645841247E-324 in positive numbers.
The Integer sub-type is a signed single byte integer value that ranges from û32,768 to 32,767. I would like to point out that there is no longer any speed advantage to using the Integer type over the Long in 32-bit environments and, of course, the Integer type has the disadvantage of a more limited value range.
The Long sub-type is a signed two-byte integer value. Its numerical range is from û2,147,483,648 to 2,147,483,647. Since Win95 and WinNT are 32-bit operating systems, they naturally do everything in 32-bit chunks. The long integer type no longer incurs a speed penalty over the integer type. I recommend that the Long be used everywhere you might have previously used the integer type.
The Object sub-type is a 32-bit address pointer reference to an OLE automation object instance. The ActiveX and Java controls are OLE Automation objects. You can set a reference to an object using the following syntax:
Set MyObject = New OleObject
At present, Visual Basic Script limits you to only the ActiveX and Java objects as OLE automation objects.
The Single sub-type is a 32-bit IEEE single precision floating point number. It has a numerical range of 6-3.402823E38 to û1.401298E-45 for negative values, and 3.402823E38 to 1.401298E-45 for positive values. Being a 32-bit number, it can show significant speed improvements over a double precision number in complex repetitive math that does not exceed the range of the single.
The String sub-type is a continuous set of character values. In Visual Basic Script this can be up to 2 billion characters. Visual Basic Script only supports variable length strings, not the fixed length strings of the full version of Visual Basic. As noted in the Byte sub-type, Visual Basic strings should not be used to manipulate binary data as was done in previous BASICs since the string now utilizes two-byte Unicode characters that could corrupt binary data under the right circumstances.
When designing your Visual Basic Script, consider this: You are writing a script program that is intended for access over the limited bandwidth of the Internet. Your Visual Basic Script program will not be compiled or optimized in any way by the server or the browser. The more raw text that needs to be sent over the network, the longer it takes to load the page. Everything you can do to compact your code's use of text lessens the time to deliver the page to the client. This is not to say that you should write cryptic code, eliminate error trapping, or otherwise compromise the professionalism of your resulting product. I am just suggesting that you attempt to use the most efficient methods and algorithms you can devise to accomplish your task.
Back to the subject at hand! Besides the limitations of only one data type, Visual Basic Script does not provide for user-defined collection objects and user-defined types. This can be a severe limitation in a normal programming environment. But this is a limited scripting version of Visual Basic optimized for use within an HTML document with the idea of placing as small a load on the network as possible.
There is also the innability to pass data by reference that requires your data variables to be global if you intend to use them from one procedure to another. You cannot pass changes to a procedural argument back to the caller. Of all the constraits in VBScript this is perhaps the greatest concerning the use of variables. It makes it very easy to have one procedure corrupt the data for another procedure. You are going to have to pay close attention when changing data values and you are going to have to validate data for both type and value.
There are two ways to create variables. You can implicitly create them where needed in a program or explicitly declare them before use. The accepted practice among most professional programmers is to explicitly declare them. In addition to explicitly declaring them, Visual Basic Script also includes the Option Explicit statement as an insurance against misspelling variable names. When used, it requires explicit declaration of a variable before attempting to use it. This prevents the programmer from common mistakes such as reusing a variable name or misspelling a variable name only to go insane later on trying to figure out why a given variable always has incorrect results in it. I strongly suggest that you use the Option Explicit statement in all of your scripts to help you eliminate as many potential bugs in your programming efforts as possible. The Option Explicit statement must be the very first line in your script for it to work properly.
If you are in a situation where you need to know the data type of a value in a variant before you use it, Visual Basic Script provides a function that tests the variant for certain data types. The VarType() function returns an integer type value that represents the data type of the variant. A set of intrinsic constants within Visual Basic Script is provided so that you can easily write code to determine the data type without having to remember these integer values (see Table 16.1).
Table 16.1 Visual Basic Script Constants for Return Values of the VarType() Function
Constant | Value | Description |
vbEmpty | 0 | Empty of any value and not initialized |
vbNull | 1 | Contains a null value |
vbInteger | 2 | Contains an integer value |
vbLong | 3 | Contains a long integer |
vbSingle | 4 | Contains a single precision floating point value |
vbDouble | 5 | Contains a double precision floating point value |
vbCurrency | 6 | Contains a currency type floating point value |
vbDate | 7 | Contains a date type value |
vbString | 8 | Contains a string type value |
vbObject | 9 | Contains a reference to an OLE automation object |
vbError | 10 | Contains an error |
vbBoolean | 11 | Contains a boolean true or false value |
vbVariant | 12 | Contains a variant |
vbDataObject | 13 | Contains a non-OLE object |
vbByte | 17 | Contains a byte value |
vbArray | 8192 | Contains an array |
Given the information in Table 16.1 you might wonder what kind of situation you would want to use this VarType() function. How about error trapping?
The example shown in Listing 16.2 sends a set of coordinates to a function that checks to see if the coordinates are within a given range of values, and returns a true or false based on that comparison. But it also checks to see if minimal values are being returned and returns an error value if these minimals are not met. Other possible uses include branching logic based on the type of data returned from a query.
Listing 16.2 Passing an Error Value a Function Result
In the case of a variant of type Array, the value returned from VarType() is a binary combination of vbArray and whatever the contained data type is. That is to say that a variant array of string types would return the value vbArray plus vbString added together. To determine that a variable is a variant array you would use a logical AND. Then, to determine the data type you can use a select case statement to determine the data type of the array as Listing 16.3 does.
Listing 16.3 Detecting Sub-Type of a Variant Array
While using the VarType() function in the proceding chapter to ensure data type in your code is an excellent way of protecting individual procedures from fatal errors due to the inadvertant passing of the wrong type, you can also take preventative steps against this and other errors by using a sensible and consistant naming convention in your scripts. Clearly, if every variable is instantly recognized as to type and purpose by its name then misuse of that variable in your code becomes less likely. There are several different naming conventions floating around in the Visual Basic community and all have their merits, and you might even develop your own. What is important is that your VBScript is consistant in those conventions. Table 16.2 provides a suggested set of prefixes for data types.
Table 16.2 Suggested VBScript Variable Naming Conventions
Prefix | Type | Example |
bln | Boolean | blnDataValid = True |
byt | Byte | bytStateFlags = bytStateFlags And &H10 |
cur | Currency | curTotal = curSubTotal + curSalesTax |
dte | Date | dteNextAppointment = NOW + 14 |
dbl | Double | dblZPlot = 375.035 * 127.999 |
int | Integer | For intCount = 1 to intMaximum |
lng | Long | For lngCount = 1 to lngMaximum |
obj | Object | Set objMyDoc = Document |
sng | Single | sngXLocation = sngMyX * 2.5 |
str | String | strUserName = strFstName & " " & strLstName |
In addition to the prefixes that identify the data type, I also recommend that you use names that clearly define the purpose of the data contained in the variable. Looking at Table 16.2 again you can see that the blnDataValid is a True/False condition of some state data's validity. If you have a set of data inputs that you validate either during input or during an attempt to submit it, this variable would represent the result of the data having been checked for valid type and range. Seems to be very obvious looking at it, but suppose I had named that same variable bDVal instead. If I had to maintain code with variables named like bDVal I would probably spend a lot of time finding out what each variable is supposed to represent as opposed to the more robust name of blnDataValid which fully describes data type and purpose.
Variables in Visual Basic Script have three levels of scope: page level scope, script level scope, and procedure level scope. The script level variables are declared right at the beginning of the script and are available to all procedures within that page's script (see Table 16.3). Variables with a procedure level scope are declared in the procedure they are used in and are visible only within the context of that procedure. Outside of procedures you declare a variable as either Private or Public. The variable that is declared as Private is visible to only the procedures within the script it is declared in. The variable that is declared as Public is visible to all of the scripts on that HTML document (see Listing 16.4).
Table 16.3 Variable Scoping in VBScript
KeyWord | Placement | Description of scope |
Dim | In Procedure | Limited to the procedure |
Dim | Not in Procedure | Visible throughout script |
Private | Not in Procedure | Visible throughout script |
Public | Not in Procedure | Visible throughout all scripts |
Listing 16.4 Examples of Variable Scope
In the example script shown in Listing 16.4, MyName has a script level scope and is visible in both button click events. The ButtonName argument to the Sub Main procedure is a procedural level variable and is visible only to the Sub Main procedure. In the BtnGoodBye Click procedure, the MyButton variable is also limited in scope to the procedure. It is a commonly accepted programming practice to limit the scope of a variable as much as possible.
With Visual Basic Script, you can pass values only by value. When you pass a variable by value, the procedure that it is passed to cannot pass the changes to the variable back up the call stack. The value is local only to the procedure. To be more specific, when you pass an argument by value, you are only passing the value contained in the variable to the procedure, and the procedure stores the value in a local replica of the variable. When you are passing a variable by reference then you are passing the address of the variable to the procedure, and the procedure directly accesses the passed variable's values. VBScript does not support passing values by reference at this time.
Visual Basic Script does not support constants or structs like the Type...End Type as in Visual Basic 4. You can either use literal values or define variables and populate them with values. Most programmers have learned to not use literals in their code due to the difficulty in maintaining such code. Instead, a good practice is to utilize constants to represent literal values throughout your projects. Since Visual Basic Script does not actually allow for constants, you have to use global variables that you initialize during runtime. Not a lot of difference in use from constants, just a slightly different way of doing it. But remember, unlike true constants, you can change the value of these variables during runtime so you should have some sort of naming convention that clearly marks them out as constants as in the example code in Listing 16.5.
Listing 16.5 Pseudo Constants
From Here...
You have seen that VBScript uses Visual Basic's Variant data type as a catch-all utility variable for all other data types. The Variant is like a sack that you can drop anything you want into. But you have to be careful that you have a method in place to keep track of what each variable contains as your scripts become more complex and as you attempt to reuse code in other projects. Where this is really going to become a problem is in the use of the ActiveX Layout control in the development of drop in place functionality. You, or someone else, will develop a control for a particular purpose and expose certain properties and methods of that control for use by the main HTML document. Knowing what kind of data type is expected for a given property by just looking at the name of that property will go a long way in helping to write bug-free code.
| Previous Chapter | Next Chapter |
| Search | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |
To order books from QUE, call us at 800-716-0044 or 317-361-5400.
For comments or technical support for our books and software, select Talk to Us.
© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.